package br.com.sis.rh.dao;

import java.util.List;

import org.apache.lucene.search.Query;
import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import br.com.sis.rh.entity.Entidade;

@SuppressWarnings("unchecked")
@Repository
public abstract class GenericDAOImpl<T> implements GenericDAO<T> {

	@Autowired
	private SessionFactory sessionFactory;
	
	private Class<T> type;
	
	public GenericDAOImpl(Class<T> classe) {
        type = classe;
	}
	
	@Override
	@Transactional
	public void incluir(T objeto) {
		sessionFactory.getCurrentSession().save(objeto);
	}

	@Override
	@Transactional
	public void alterar(T objeto) {
		sessionFactory.getCurrentSession().update(objeto);
	}

	@Override
	@Transactional
	public void excluir(T objeto) {
		sessionFactory.getCurrentSession().delete(objeto);
	}
	
	@Override
	@Transactional
	public List<T> listar(T objeto) {
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(objeto.getClass());

		return (List<T>) criteria.list();
	}

	@Override
	@Transactional
	public List<T> listarHS(T objeto, String[] campos, String valor) {
		FullTextSession fullTextSession = Search.getFullTextSession(sessionFactory.getCurrentSession());
		
		QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(type).get();
		
		Query luceneQuery = qb.keyword().onFields(campos).matching(valor).createQuery();
		
		org.hibernate.Query hibQuery = fullTextSession.createFullTextQuery(luceneQuery, type);
		
		List<T> lista = hibQuery.list();
		
		return (List<T>) lista;
	}
	
	@Override
	@Transactional
	public T recuperarObjetoPorID(Object objeto) {
		T objetoRecuperado = null;
		
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(objeto.getClass());

		Entidade comum = (Entidade) objeto;
		
		criteria.add(Restrictions.eq("id",  comum.getId()));
		
		List<T> c = (List<T>) criteria.list();
		
		if(!c.isEmpty()) {
			objetoRecuperado = c.get(0);	
		} 
		
		return objetoRecuperado;
	}
}
